home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / daten / astrolog / src / charts2.c < prev    next >
C/C++ Source or Header  |  1995-08-11  |  30KB  |  1,061 lines

  1. /*                                                               -*- C -*-
  2. ** Astrolog (Version 4.40) File: charts2.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (astara@u.washington.edu). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 1/29/1995.
  35. */
  36.  
  37. /* $VER: $Id: charts2.c,v 1.2 1995/07/02 22:21:02 tf Exp $ */
  38.  
  39. #include "astrolog.h"
  40.  
  41.  
  42. /*
  43. ******************************************************************************
  44. ** Dual Chart Display Routines.
  45. ******************************************************************************
  46. */
  47.  
  48. /* Print out an aspect (or midpoint if -g0 switch in effect) grid of a      */
  49. /* relationship chart. This is similar to the ChartGrid() routine; however, */
  50. /* here we have both axes labeled with the planets for the two charts in    */
  51. /* question, instead of just a diagonal down the center for only one chart. */
  52.  
  53. void ChartGridRelation()
  54. {
  55.   char sz[cchSzDef];
  56.   int i, j, k, tot = cObj, temp;
  57.  
  58. #ifdef INTERPRET
  59.   if (us.fInterpret && !us.fGridConfig) 
  60.   {
  61.     InterpretGridRelation();
  62.     return;
  63.   }
  64. #endif
  65.   PrintSz(" 2>");
  66.   for (temp = 0, i = 1; i <= cObj; i++) if (!ignore[i])
  67.   {
  68.     PrintCh(chV);
  69.     AnsiColor(kObjA[i]);
  70.     sprintf(sz, "%c%c%c", chObj3(i)); PrintSz(sz);
  71.     AnsiColor(kDefault);
  72.     temp++;
  73.   }
  74.   PrintSz("\n1  ");
  75.   for (i = 1; i <= tot; i++) if (!ignore[i])
  76.   {
  77.     PrintCh(chV);
  78.     AnsiColor(kSignA(SFromZ(cp2.obj[i])));
  79.     sprintf(sz, "%2d%c", (int)cp2.obj[i] % 30, chDeg0); PrintSz(sz);
  80.     AnsiColor(kDefault);
  81.   }
  82.   PrintSz("\nV  ");
  83.   for (i = 1; i <= tot; i++) if (!ignore[i])
  84.   {
  85.     PrintCh(chV);
  86.     temp = SFromZ(cp2.obj[i]);
  87.     AnsiColor(kSignA(temp));
  88.     sprintf(sz, "%c%c%c", chSig3(temp)); PrintSz(sz);
  89.     AnsiColor(kDefault);
  90.   }
  91.   PrintL();
  92.   for (j = 1; j <= cObj; j++) if (!ignore[j])
  93.   {
  94.     for (k = 1; k <= 4; k++)
  95.     {
  96.       if (k < 2)
  97.         PrintTab(chH, 3);
  98.  
  99.       else if (k == 2)
  100.       {
  101.         AnsiColor(kObjA[j]);
  102.         sprintf(sz, "%c%c%c", chObj3(j)); PrintSz(sz);
  103.       }
  104.  
  105.       else
  106.       {
  107.         temp = SFromZ(cp1.obj[j]);
  108.         AnsiColor(kSignA(temp));
  109.         if (k == 3)
  110.           sprintf(sz, "%2d%c", (int)cp1.obj[j] - (temp-1)*30, chDeg0);
  111.         else
  112.           sprintf(sz, "%c%c%c", chSig3(temp));
  113.         PrintSz(sz);
  114.       }
  115.       if (k > 1)
  116.         AnsiColor(kDefault);
  117.  
  118.       for (i = 1; i <= tot; i++) if (!ignore[i])
  119.       {
  120.         PrintCh((char)(k < 2 ? chC : chV));
  121.         temp = grid->n[i][j];
  122.  
  123.         if (k > 1)
  124.         {
  125.           if (i == j)
  126.             AnsiColor(kReverse);
  127.           AnsiColor(us.fGridConfig ? kSignA(temp) :
  128.             kAspA[temp]);
  129.         }
  130.  
  131.         if (k < 2)
  132.           PrintTab(chH, 3);
  133.  
  134.         else if (k == 2)
  135.         {
  136.           if (us.fGridConfig)
  137.             sprintf(sz, "%c%c%c", chSig3(temp));
  138.           else
  139.             sprintf(sz, "%s", temp ? szAspectAbbrev[temp] : "   ");
  140.           PrintSz(sz);
  141.         } 
  142.  
  143.         else if (k == 3)
  144.         {
  145.           if (us.fGridConfig)
  146.           {
  147.             sprintf(sz, "%2d%c", grid->v[i][j]/60, chDeg0); PrintSz(sz);
  148.           }
  149.           else if (grid->n[i][j])
  150.           {
  151.             if (grid->v[i][j] < 6000)
  152.               sprintf(sz, "%c%2d", us.fAppSep ? (grid->v[i][j] < 0 ? 'a' : 's')
  153.                                               : (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60);
  154.             else
  155.               sprintf(sz, "%3d", abs(temp)/60);
  156.  
  157.             PrintSz(sz);
  158.           }
  159.           else PrintSz("   ");
  160.         }
  161.  
  162.         else
  163.         {
  164.           if (grid->n[i][j])
  165.           {
  166.             sprintf(sz, "%02d'", abs(grid->v[i][j])%60); PrintSz(sz);
  167.           }
  168.           else
  169.             PrintSz("   ");
  170.         }
  171.  
  172.         AnsiColor(kDefault);
  173.       }
  174.       PrintL();
  175.     }
  176.   }
  177. }
  178.  
  179.  
  180. /* Display all aspects between objects in the relationship comparison chart, */
  181. /* one per line, in sorted order based on the total "power" of the aspects,  */
  182. /* as specified with the -r0 -a switch combination.                          */
  183.  
  184. void ChartAspectRelation()
  185. {
  186.   char sz[cchSzDef];
  187.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  188.   real ip, jp;
  189.  
  190.   loop
  191.   {
  192.     phi = -1;
  193.  
  194.     /* Search for the next most powerful aspect in the aspect grid. */
  195.  
  196.     for (i = 1; i <= cObj; i++) if (!ignore[i])
  197.     {
  198.       for (j = 1; j <= cObj; j++) if (!ignore[j])
  199.       {
  200.         if (k = grid->n[i][j]) 
  201.         {
  202.           ip = i <= oNorm ? objectinf[i] : 2.5;
  203.           jp = j <= oNorm ? objectinf[j] : 2.5;
  204.           p = (int)(aspectinf[k]*(ip+jp)/2.0 * (1.0-RAbs((real)(grid->v[i][j]))/60.0/aspectorb[k])*1000.0);
  205.  
  206.           if ((p < pcut || (p == pcut && (i > icut || (i == icut && j > jcut)))) && p > phi)
  207.           {
  208.             ihi = i; jhi = j; phi = p; ahi = k;
  209.           }
  210.         }
  211.       }
  212.     }
  213.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  214.       break;
  215.  
  216.     pcut = phi; icut = ihi; jcut = jhi;
  217.     count++;                              /* Display the current aspect.   */
  218. #ifdef INTERPRET
  219.     if (us.fInterpret)                    /* Interpret it if -I in effect. */
  220.     {
  221.       InterpretAspectRelation(jhi, ihi);
  222.       continue;
  223.     }
  224. #endif
  225.     sprintf(sz, "%3d: ", count); PrintSz(sz);
  226.  
  227.     PrintAspect(jhi, SFromZ(cp1.obj[jhi]), (int)RSgn(cp1.dir[jhi]), ahi,
  228.       ihi, SFromZ(cp2.obj[ihi]), (int)RSgn(cp2.dir[ihi]), 'A');
  229.  
  230.     k = grid->v[ihi][jhi];
  231.     AnsiColor(k < 0 ? kWhite : kLtGray);
  232.  
  233.     sprintf(sz, "- orb: %c%d,%02d'",
  234.       us.fAppSep ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  235.       abs(k)/60, abs(k)%60); PrintSz(sz);
  236.  
  237.     AnsiColor(kDkGreen);
  238.     sprintf(sz, " - power:%6.2f\n", (real)phi/1000.0); PrintSz(sz);
  239.     AnsiColor(kDefault);
  240.   }
  241. }
  242.  
  243.  
  244. /* Display locations of all midpoints between objects in the relationship */
  245. /* comparison chart, one per line, in sorted zodiac order from zero Aries */
  246. /* onward, as specified with the -r0 -m switch combination.               */
  247.  
  248. void ChartMidpointRelation()
  249. {
  250.   char sz[cchSzDef];
  251.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
  252.  
  253.   loop {
  254.     mlo = 21600;
  255.  
  256.     /* Search for the next closest midpoint farther down in the zodiac. */ 
  257.  
  258.     for (i = 1; i <= cObj; i++) if (!ignore[i])
  259.     {
  260.       for (j = 1; j <= cObj; j++) if (!ignore[j])
  261.       {
  262.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  263.  
  264.         if ((m > mcut || (m == mcut && (i > icut || (i == icut && j > jcut)))) && m < mlo)
  265.         {
  266.           ilo = i; jlo = j; mlo = m;
  267.         }
  268.       }
  269.     }
  270.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  271.       break;
  272.     mcut = mlo; icut = ilo; jcut = jlo;
  273.     count++;                               /* Display the current midpoint. */
  274.  
  275. #ifdef INTERPRET
  276.     if (us.fInterpret)                     /* Interpret it if -I in effect. */
  277.     {
  278.       InterpretMidpointRelation(ilo, jlo);
  279.       continue;
  280.     }
  281. #endif
  282.     sprintf(sz, "%4d: ", count); PrintSz(sz);
  283.     PrintZodiac((real)mlo/60.0);
  284.     PrintCh(' ');
  285.  
  286.     PrintAspect(ilo, SFromZ(cp1.obj[ilo]), (int)RSgn(cp1.dir[ilo]), 0,
  287.       jlo, SFromZ(cp2.obj[jlo]), (int)RSgn(cp2.dir[jlo]), 'M');
  288.  
  289.     AnsiColor(kDefault);
  290.     m = (int)(MinDistance(cp1.obj[ilo], cp2.obj[jlo])*60.0);
  291.     sprintf(sz, "-%4d%c%02d' degree span.\n", m/60, chDeg1, m%60);
  292.     PrintSz(sz);
  293.   }
  294. }
  295.  
  296.  
  297. /* Calculate any of the various kinds of relationship charts. This involves */
  298. /* reading in and storing the planet and house positions for both charts,   */
  299. /* and then combining them in the main single chart in the proper manner.   */
  300. /* If the parameter 'fFile' is on, then we read the info for the two charts */
  301. /* from files, otherwise use the info in preset "core" and "second" charts. */
  302.  
  303. void CastRelation(fFile)
  304. bool fFile;
  305. {
  306.   byte ignoreT[objMax];
  307.   CI ciT;
  308.   int i;
  309.   real ratio, t1, t2, t;
  310.  
  311.   /* Read in and cast the first chart. */
  312.  
  313.   if (fFile)
  314.     FInputData(is.szFile);
  315.  
  316.   ciT = ciCore;
  317.  
  318.   if (fFile)
  319.     ciTwin = ciCore;
  320.   else
  321.     ciCore = ciTwin;
  322.  
  323.   t1 = CastChart(fTrue);
  324.  
  325.   for (i = 1; i <= cSign; i++)
  326.   {
  327.     cp1.cusp[i] = house[i];
  328.     cp1.house[i] = inhouse[i];
  329.   }
  330.  
  331.   for (i = 1; i <= cObj; i++)
  332.   {
  333.     cp1.obj[i] = planet[i];
  334.     cp1.alt[i] = planetalt[i];
  335.     cp1.dir[i] = ret[i];
  336.   }
  337.  
  338.   /* Read in the second chart. */
  339.  
  340.   if (fFile)
  341.   {
  342.     FInputData(is.szFile2);
  343.     if (us.nRel == rcProgress)
  344.     {
  345.       us.fProgress = fTrue;
  346.       is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  347.       ciCore = ciT;
  348.     }
  349.   }
  350.   else ciCore = ciT;
  351.  
  352.   ciMain = ciCore;
  353.  
  354.   if (us.nRel == rcTransit)
  355.   {
  356.     for (i = 1; i <= cObj; i++)
  357.     {
  358.       ignoreT[i] = ignore[i];
  359.       ignore[i] = ignore[i] && ignore2[i];
  360.     }
  361.   }
  362.  
  363.   t2 = CastChart(fTrue);
  364.  
  365.   if (us.nRel == rcTransit)
  366.   {
  367.     for (i = 1; i <= cObj; i++)
  368.       ignore[i] = ignoreT[i];
  369.   }
  370.  
  371.   for (i = 1; i <= cSign; i++)
  372.   {
  373.     cp2.cusp[i] = house[i];
  374.     cp2.house[i] = inhouse[i];
  375.   }
  376.  
  377.   for (i = 1; i <= cObj; i++)
  378.   {
  379.     cp2.obj[i] = planet[i];
  380.     cp2.alt[i] = planetalt[i];
  381.     cp2.dir[i] = ret[i];
  382.   }
  383.  
  384.   /* Now combine the two charts based on what relation we are doing.   */
  385.   /* For the standard -r synastry chart, use the house cusps of chart1 */
  386.   /* and the planets positions of chart2.                              */
  387.  
  388.   ratio = (real)us.nRatio1 / ((real)(us.nRatio1 + us.nRatio2));
  389.  
  390.   if (us.nRel <= rcSynastry)
  391.   {
  392.     for (i = 1; i <= cSign; i++)
  393.       house[i] = cp1.cusp[i];
  394.   }
  395.  
  396.   /* For the -rc composite chart, take the midpoints of the planets/houses. */
  397.  
  398.   else if (us.nRel == rcComposite)
  399.   {
  400.     for (i = 1; i <= cObj; i++)
  401.     {
  402.       planet[i] = Ratio(cp1.obj[i], cp2.obj[i], ratio);
  403.       if (RAbs(cp2.obj[i] - cp1.obj[i]) > rDegHalf)
  404.         planet[i] = Mod(planet[i] + rDegMax*ratio);
  405.       planetalt[i] = Ratio(cp1.alt[i], cp2.alt[i], ratio);
  406.       ret[i] = Ratio(cp1.dir[i], cp2.dir[i], ratio);
  407.     }
  408.  
  409.     for (i = 1; i <= cSign; i++)
  410.     {
  411.       house[i] = Ratio(cp1.cusp[i], cp2.cusp[i], ratio);
  412.       if (RAbs(cp2.cusp[i] - cp1.cusp[i]) > rDegHalf)
  413.         house[i] = Mod(house[i] + rDegMax*ratio);
  414.     }
  415.  
  416.     /* Make sure we don't have any 180 degree errors in house cusp    */
  417.     /* complement pairs, which may happen if the cusps are far apart. */
  418.  
  419.     for (i = 1; i <= cSign; i++)
  420.       if (MinDistance(house[sCap], Mod(house[i]-ZFromS(i+3))) > rDegQuad)
  421.         house[i] = Mod(house[i]+rDegHalf);
  422.  
  423.     for (i = 1; i <= cSign; i++)
  424.       if (RAbs(MinDistance(house[i], planet[oAsc - 1 + i])) > rDegQuad)
  425.         planet[oAsc - 1 + i] = Mod(planet[oAsc - 1 + i]+rDegHalf);
  426.   }
  427.  
  428.   /* For the -rm time space midpoint chart, calculate the midpoint time and */
  429.   /* place between the two charts and then recast for the new chart info.   */
  430.  
  431.   else if (us.nRel == rcMidpoint)
  432.   {
  433.     T = Ratio(t1, t2, ratio);
  434.     t = (T*36525.0)+rRound; is.JD = RFloor(t)+2415020.0; TT = RFract(t)*24.0;
  435.     ZZ = Ratio(DecToDeg(ciT.zon), DecToDeg(Zon), ratio);
  436.     SS = Ratio(DecToDeg(ciT.dst), DecToDeg(Dst), ratio);
  437.     TT -= ZZ;
  438.     if (TT < 0.0) {
  439.       TT += 24.0; is.JD -= 1.0;
  440.     }
  441.     JulianToMdy(is.JD, &MM, &DD, &YY);
  442.     OO = Ratio(DecToDeg(ciT.lon), DecToDeg(Lon), ratio);
  443.     if (RAbs(Lon-ciT.lon) > rDegHalf)
  444.       OO = Mod(OO+rDegMax*ratio);
  445.     AA = Ratio(DecToDeg(ciT.lat), DecToDeg(Lat), ratio);
  446.     TT = DegToDec(TT); SS = DegToDec(SS); ZZ = DegToDec(ZZ);
  447.     OO = DegToDec(OO); AA = DegToDec(AA);
  448.     ciMain = ciCore;
  449.     CastChart(fTrue);
  450.  
  451.   /* There are a couple of non-astrological charts, which only require the */
  452.   /* number of days that have passed between the two charts to be done.    */
  453.  
  454.   } else
  455.     is.JD = RAbs(t2-t1)*36525.0;
  456.   ComputeInHouses();
  457. }
  458.  
  459.  
  460. /*
  461. ******************************************************************************
  462. ** Other Chart Display Routines.
  463. ******************************************************************************
  464. */
  465.  
  466. /* Given two objects and an aspect between them, or an object and a sign  */
  467. /* that it's entering, print if this is a "major" event, such as a season */
  468. /* change or major lunar phase. This is called from the ChartInDay()      */
  469. /* searching and influence routines. Do an interpretation if need be too. */
  470.  
  471. void PrintInDay(source, aspect, dest)
  472. int source, aspect, dest;
  473. {
  474.   if (aspect == aSig)
  475.   {
  476.     if (source == oSun)
  477.     {
  478.       AnsiColor(kWhite);
  479.       if (dest == 1)
  480.         PrintSz(" (Vernal Equinox)");     /* If the Sun changes sign, */
  481.       else if (dest == 4)                 /* then print out if this   */
  482.         PrintSz(" (Summer Solstice)");    /* is a season change.      */
  483.       else if (dest == 7)
  484.         PrintSz(" (Autumnal Equinox)");
  485.       else if (dest == 10)
  486.         PrintSz(" (Winter Solstice)");
  487.     }
  488.   } 
  489.  
  490.   else if (aspect > 0)
  491.   {
  492.     if (source == oSun && dest == oMoo)
  493.     {
  494.       if (aspect <= aSqu)
  495.         AnsiColor(kWhite);
  496.       if (aspect == aCon)
  497.         PrintSz(" (New Moon)");     /* Print out if the present */
  498.       else if (aspect == aOpp)      /* aspect is a New, Full,   */
  499.         PrintSz(" (Full Moon)");    /* or Half Moon.            */
  500.       else if (aspect == aSqu)
  501.         PrintSz(" (Half Moon)");
  502.     }
  503.   }
  504.   PrintL();
  505.  
  506. #ifdef INTERPRET
  507.   if (us.fInterpret)
  508.     InterpretInDay(source, aspect, dest);
  509. #endif
  510.   AnsiColor(kDefault);
  511. }
  512.  
  513.  
  514. /* Given two objects and an aspect (or one object, and an event such as a */
  515. /* sign or direction change) display the configuration in question. This  */
  516. /* is called by the many charts which list aspects among items, such as   */
  517. /* the -a aspect lists, -m midpoint lists, -d aspect in day search and    */
  518. /* influence charts, and -t transit search and influence charts.          */
  519.  
  520. void PrintAspect(obj1, sign1, ret1, asp, obj2, sign2, ret2, chart)
  521. int obj1, sign1, ret1, asp, obj2, sign2, ret2;
  522. char chart;
  523. {
  524.   char sz[cchSzDef];
  525.  
  526.   AnsiColor(kObjA[obj1]);
  527.  
  528.   if (chart == 't' || chart == 'T')
  529.     PrintSz("trans ");
  530.   else if (chart == 'e' || chart == 'u' || chart == 'U')
  531.     PrintSz("progr ");
  532.  
  533.   sprintf(sz, "%7.7s", szObjName[obj1]); PrintSz(sz);
  534.   AnsiColor(kSignA(sign1));
  535.  
  536.   sprintf(sz, " %c%c%c%c%c",
  537.     ret1 > 0 ? '(' : (ret1 < 0 ? '[' : '<'), chSig3(sign1),
  538.     ret1 > 0 ? ')' : (ret1 < 0 ? ']' : '>')); PrintSz(sz);
  539.  
  540.   AnsiColor(asp > 0 ? kAspA[asp] : kWhite);
  541.   PrintCh(' ');
  542.  
  543.   if (asp == aSig)
  544.     sprintf(sz, "-->");                        /* Print a sign change. */
  545.   else if (asp == aDir)
  546.     sprintf(sz, "S/%c", obj2 ? chRet : 'D');   /* Print a direction change. */
  547.   else if (asp == 0)
  548.     sprintf(sz, chart == 'm' ? "&" : "with");
  549.   else
  550.     sprintf(sz, "%s", szAspectAbbrev[asp]);    /* Print an aspect. */
  551.  
  552.   PrintSz(sz);
  553.   if (asp != aDir)
  554.     PrintCh(' ');
  555.   if (chart == 'A')
  556.     PrintSz("with ");
  557.  
  558.   if (asp == aSig)
  559.   {
  560.     AnsiColor(kSignA(obj2));
  561.     sprintf(sz, "%s", szSignName[obj2]); PrintSz(sz);
  562.   }
  563.  
  564.   else if (asp >= 0)
  565.   {
  566.     AnsiColor(kSignA(sign2));
  567.     if (chart == 't' || chart == 'u' || chart == 'T' || chart == 'U')
  568.       PrintSz("natal ");
  569.  
  570.     sprintf(sz, "%c%c%c%c%c ",
  571.       ret2 > 0 ? '(' : (ret2 < 0 ? '[' : '<'), chSig3(sign2),
  572.       ret2 > 0 ? ')' : (ret2 < 0 ? ']' : '>')); PrintSz(sz);
  573.  
  574.     AnsiColor(kObjA[obj2]);
  575.     sprintf(sz, "%.10s", szObjName[obj2]); PrintSz(sz);
  576.   }
  577.  
  578.   if (chart == 'D' || chart == 'T' || chart == 'U' ||
  579.       chart == 'a' || chart == 'A' || chart == 'm' || chart == 'M')
  580.     PrintTab(' ', 10-CchSz(szObjName[obj2]));
  581. }
  582.  
  583.  
  584. /* Based on the given chart information, display all the aspects taking   */
  585. /* place in the chart, as specified with the -D switch. The aspects are   */
  586. /* printed in order of influence determined by treating them as happening */
  587. /* outside among transiting planets, such that rare outer planet aspects  */
  588. /* are given more power than common ones among inner planets. (This is    */
  589. /* almost identical to the -a list, except the influences are different.) */
  590.  
  591. void ChartInDayInfluence()
  592. {
  593.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  594.   real power[MAXINDAY];
  595.   char sz[cchSzDef];
  596.   int occurcount = 0, i, j, k, l, m;
  597.  
  598.   /* Go compute the aspects in the chart. */
  599.  
  600.   i = us.fAppSep;
  601.   us.fAppSep = fTrue;     /* We always want applying vs. separating orbs. */
  602.   FCreateGrid(fFalse);
  603.   us.fAppSep = i;
  604.  
  605.   /* Search through the grid and build up the list of aspects. */
  606.  
  607.   for (j = 2; j <= cObj; j++)
  608.   {
  609.     if (ignore[j])
  610.       continue;
  611.     for (i = 1; i < j; i++)
  612.     {
  613.       if (ignore[i] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  614.         continue;
  615.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  616.       l = grid->v[i][j];
  617.       power[occurcount] =
  618.         ((i <= oNorm ? transitinf[i] : 2.0)/4.0)*
  619.         ((j <= oNorm ? transitinf[j] : 2.0)/4.0)*
  620.         aspectinf[k]*(1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  621.       occurcount++;
  622.     }
  623.   }
  624.  
  625.   /* Sort aspects by order of influence. */
  626.  
  627.   for (i = 1; i < occurcount; i++)
  628.   {
  629.     j = i-1;
  630.     while (j >= 0 && power[j] < power[j+1])
  631.     {
  632.       SwapN(source[j], source[j+1]);
  633.       SwapN(aspect[j], aspect[j+1]);
  634.       SwapN(dest[j], dest[j+1]);
  635.       SwapR(&power[j], &power[j+1]);
  636.       j--;
  637.     }
  638.   }
  639.  
  640.   /* Now display each aspect line. */
  641.  
  642.   for (i = 0; i < occurcount; i++)
  643.   {
  644.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  645.     j = source[i]; k = aspect[i]; l = dest[i];
  646.  
  647.     PrintAspect(
  648.       j, SFromZ(planet[j]), (int)RSgn(ret[j]), k,
  649.       l, SFromZ(planet[l]), (int)RSgn(ret[l]), 'D');
  650.  
  651.     m = grid->v[j][l];
  652.     AnsiColor(m < 0 ? kWhite : kLtGray);
  653.  
  654.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  655.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  656.  
  657.     AnsiColor(kDkGreen);
  658.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  659.     PrintInDay(j, k, l);
  660.   }
  661. }
  662.  
  663.  
  664. /* Given an arbitrary day, determine what aspects are made between this */
  665. /* transiting chart and the given natal chart, as specified with the -T */
  666. /* switch, and display the transits in order sorted by influence.       */
  667.  
  668. void ChartTransitInfluence(fProg)
  669. bool fProg;
  670. {
  671.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  672.   real power[MAXINDAY];
  673.   byte ignore3[objMax];
  674.   char sz[cchSzDef];
  675.   int occurcount = 0, i, j, k, l, m;
  676.  
  677.   /* Cast the natal and transiting charts as with a relationship chart. */
  678.  
  679.   for (i = 1; i <= cSign; i++)
  680.     cp1.cusp[i] = house[i];
  681.  
  682.   for (i = 1; i <= cObj; i++)
  683.   {
  684.     cp1.obj[i] = planet[i];
  685.     cp1.dir[i] = ret[i];
  686.   }
  687.  
  688.   ciCore = ciTwin;
  689.  
  690.   if (us.fProgress = fProg)
  691.   {
  692.     is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  693.     ciCore = ciMain;
  694.   }
  695.   CastChart(fTrue);
  696.  
  697.   for (i = 1; i <= cSign; i++)
  698.     cp2.cusp[i] = house[i];
  699.  
  700.   for (i = 1; i <= cObj; i++)
  701.   {
  702.     cp2.obj[i] = planet[i];
  703.     cp2.dir[i] = ret[i];
  704.   }
  705.  
  706.   /* Do a relationship aspect grid to get the transits. We have to make and */
  707.   /* restore three changes to get it right for this chart. (1) We make the  */
  708.   /* natal planets have zero velocity so applying vs. separating is only a  */
  709.   /* function of the transiter. (2) We force applying vs. separating orbs   */
  710.   /* regardless if -ga or -ma is in effect or not. (3) Finally we tweak the */
  711.   /* main restrictions to allow for transiting objects not restricted.      */
  712.  
  713.   for (i = 1; i <= cObj; i++)
  714.   {
  715.     ret[i] = cp1.dir[i];
  716.     cp1.dir[i] = 0.0;
  717.     ignore3[i] = ignore[i];
  718.     ignore[i] = ignore[i] && ignore2[i];
  719.   }
  720.   i = us.fAppSep;
  721.   us.fAppSep = fTrue;
  722.   FCreateGridRelation(fFalse);
  723.   us.fAppSep = i;
  724.   for (i = 1; i <= cObj; i++)
  725.   {
  726.     cp1.dir[i] = ret[i];
  727.     ignore[i] = ignore3[i];
  728.   }
  729.  
  730.   /* Loop through the grid, and build up a list of the valid transits. */
  731.  
  732.   for (i = 1; i <= oNorm; i++)
  733.   {
  734.     if (ignore2[i] || !FThing(i))
  735.       continue;
  736.     for (j = 1; j <= cObj; j++)
  737.     {
  738.       if (ignore[j] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  739.         continue;
  740.  
  741.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  742.       l = grid->v[i][j];
  743.  
  744.       power[occurcount] = transitinf[i]*
  745.         ((j <= oNorm ? objectinf[j] : 2.0)/4.0)*aspectinf[k]*
  746.         (1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  747.       occurcount++;
  748.     }
  749.   }
  750.  
  751.   /* After all transits located, sort them by their total power. */
  752.  
  753.   for (i = 1; i < occurcount; i++)
  754.   {
  755.     j = i-1;
  756.     while (j >= 0 && power[j] < power[j+1])
  757.     {
  758.       SwapN(source[j], source[j+1]);
  759.       SwapN(aspect[j], aspect[j+1]);
  760.       SwapN(dest[j], dest[j+1]);
  761.       SwapR(&power[j], &power[j+1]);
  762.       j--;
  763.     }
  764.   }
  765.  
  766.   /* Now loop through list and display each transit in effect at the time. */
  767.  
  768.   for (i = 0; i < occurcount; i++)
  769.   {
  770.     k = aspect[i];
  771.     l = source[i];
  772.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  773.     j = SFromZ(cp2.obj[l]);
  774.     PrintAspect(l, j, (int)RSgn(cp2.dir[l]), k,
  775.       dest[i], SFromZ(cp1.obj[dest[i]]), (int)RSgn(cp1.dir[dest[i]]),
  776.       (char)(fProg ? 'U' : 'T'));
  777.     m = grid->v[l][dest[i]];
  778.     AnsiColor(m < 0 ? kWhite : kLtGray);
  779.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  780.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  781.     AnsiColor(kDkGreen);
  782.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  783.     if (k == aCon && l == dest[i]) {    /* Print a small "R" for returns. */
  784.       AnsiColor(kWhite);
  785.       PrintSz(" R");
  786.     }
  787.     PrintL();
  788. #ifdef INTERPRET
  789.     if (us.fInterpret)
  790.       InterpretTransit(l, k, dest[i]);
  791. #endif
  792.     AnsiColor(kDefault);
  793.   }
  794. }
  795.  
  796.  
  797. /* Given the zodiac location of a planet in the sky and its declination,   */
  798. /* and a location on the Earth, compute the azimuth and altitude of where  */
  799. /* on the local horizon sky the planet would appear to one at the given    */
  800. /* location. A reference MC position at Greenwich is also needed for this. */
  801.  
  802. void EclToHorizon(azi, alt, planet, planetalt, lon, lat, mc)
  803. real *azi, *alt, planet, planetalt, lon, lat, mc;
  804. {
  805.   real lonz, latz;
  806.  
  807.   lonz = RFromD(planet); latz = RFromD(planetalt);
  808.   EclToEqu(&lonz, &latz);
  809.   lonz = RFromD(Mod(DFromR(mc-lonz+lon)));
  810.   lonz = RFromD(Mod(DFromR(lonz-lon+rPiHalf)));
  811.   EquToLocal(&lonz, &latz, rPiHalf-lat);
  812.   *azi = rDegMax-DFromR(lonz); *alt = DFromR(latz);
  813. }
  814.  
  815.  
  816. /* Display a calendar for the given month in the chart, as specified with  */
  817. /* with the -K switch. When color is on, the title is white, weekends are  */
  818. /* highlighted in red, and the specific day in the chart is colored green. */
  819.  
  820. void ChartCalendarMonth()
  821. {
  822.   char sz[cchSzDef];
  823.   int i, j, k;
  824.  
  825.   AnsiColor(kWhite);
  826.   PrintTab(' ', 16-CchSz(szMonth[Mon]) >> 1);
  827.   sprintf(sz, "%s%5d\n", szMonth[Mon], Yea); PrintSz(sz);
  828.   for (i = 0; i < 7; i++) {
  829.     sprintf(sz, "%c%c%c", szDay[i][0], szDay[i][1], i < 6 ? ' ' : '\n');
  830.     PrintSz(sz);
  831.   }
  832.   j = DayOfWeek(Mon, 1, Yea);
  833.   AnsiColor(kDefault);
  834.  
  835.   for (i = 0; i < j; i++)
  836.   {
  837.     if (i == 0)
  838.       AnsiColor(kRainbowA[1]);
  839.     PrintSz("-- ");
  840.     if (i == 0)
  841.       AnsiColor(kDefault);
  842.   }
  843.  
  844.   k = DayInMonth(Mon, Yea);
  845.   for (i = 1; i <= k; i = AddDay(Mon, i, Yea, 1))
  846.   {
  847.     if (i == (int)Day)
  848.       AnsiColor(kRainbowA[4]);
  849.     else if (j == 0 || j == 6)
  850.       AnsiColor(kRainbowA[1]);
  851.     sprintf(sz, "%2d", i); PrintSz(sz);
  852.     if (j == 0 || j == 6 || i == Day)
  853.       AnsiColor(kDefault);
  854.  
  855.     if (j < 6)
  856.     {
  857.       j++;
  858.       PrintCh(' ');
  859.     }
  860.     else
  861.     {
  862.       j = 0;
  863.       PrintL();
  864.     }
  865.   }
  866.  
  867.   while (j > 0 && j < 7)
  868.   {
  869.     if (j == 6)
  870.       AnsiColor(kRainbowA[1]);
  871.     j++;
  872.     sprintf(sz, "--%c", j < 7 ? ' ' : '\n'); PrintSz(sz);
  873.   }
  874.   AnsiColor(kDefault);
  875. }
  876.  
  877.  
  878. /* Display a calendar for the entire year given in the chart, as specified */
  879. /* with the -Ky switch. This is just like twelve of the individual month   */
  880. /* calendars above displayed together, with same color highlights and all. */
  881.  
  882. void ChartCalendarYear()
  883. {
  884.   char sz[cchSzDef];
  885.   int r, w, c, m, d, dy, p[3], l[3], n[3];
  886.  
  887.   dy = DayOfWeek(1, 1, Yea);
  888.   for (r = 0; r < 4; r++)      /* Loop over one set of three months */
  889.   {
  890.     AnsiColor(kWhite);
  891.     for (c = 0; c < 3; c++)
  892.     {
  893.       m = r*3+c+1;
  894.       PrintTab(' ', 16-CchSz(szMonth[m]) >> 1);
  895.       sprintf(sz, "%s%5d", szMonth[m], Yea); PrintSz(sz);
  896.       if (c < 2)
  897.         PrintTab(' ', 20 + MONTHSPACE -
  898.           (16-CchSz(szMonth[m]) >> 1) - CchSz(szMonth[m]) - 5);
  899.     }
  900.     PrintL();
  901.  
  902.     for (c = 0; c < 3; c++)
  903.     {
  904.       for (d = 0; d < 7; d++)
  905.       {
  906.         sprintf(sz, "%c%c%c", szDay[d][0], szDay[d][1],
  907.           d < 6 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  908.       }
  909.  
  910.       if (c < 2)
  911.         PrintTab(' ', MONTHSPACE-1);
  912.  
  913.       m = r*3+c+1;
  914.       p[c] = dy % 7;
  915.       l[c] = DayInMonth(m, Yea);
  916.       n[c] = 0;
  917.       dy += DaysInMonth(m, Yea);
  918.     }
  919.     for (w = 0; w < 6; w++)        /* Loop over one set of week rows */
  920.     {
  921.       for (c = 0; c < 3; c++)      /* Loop over one week in a month  */
  922.       {
  923.         m = r*3+c+1;
  924.         d = 0;
  925.  
  926.         if (w == 0)
  927.         {
  928.           while (d < p[c])
  929.           {
  930.             if (d == 0)
  931.               AnsiColor(kRainbowA[1]);
  932.             PrintSz("-- ");
  933.             if (d == 0)
  934.               AnsiColor(kDefault);
  935.             d++;
  936.           }
  937.         }
  938.  
  939.         AnsiColor(kDefault);
  940.         while (d < 7 && n[c] < l[c])
  941.         {
  942.           n[c] = AddDay(m, n[c], Yea, 1);
  943.  
  944.           if (n[c] == Day && m == Mon)
  945.             AnsiColor(kRainbowA[4]);
  946.           else if (d == 0 || d == 6)
  947.             AnsiColor(kRainbowA[1]);
  948.  
  949.           sprintf(sz, "%2d%c", n[c], d < 6 || c < 2 ? ' ' : '\n');
  950.           PrintSz(sz);
  951.           if (d == 0 || d == 6 || (n[c] == Day && m == Mon))
  952.             AnsiColor(kDefault);
  953.           d++;
  954.         }
  955.         while (d < 7)
  956.         {
  957.           if (d == 0 || d == 6)
  958.             AnsiColor(kRainbowA[1]);
  959.  
  960.           sprintf(sz, "--%c", d < 6 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  961.           if (d == 0)
  962.             AnsiColor(kDefault);
  963.           d++;
  964.         }
  965.         if (c < 2)
  966.           PrintTab(' ', MONTHSPACE-1);
  967.       }
  968.     }
  969.     if (r < 3)
  970.       PrintL();
  971.   }
  972.   AnsiColor(kDefault);
  973. }
  974.  
  975.  
  976. /* Display either a biorhythm chart or the time difference in various units */
  977. /* between two charts, i.e. two types of relationship "charts" that aren't  */
  978. /* related in any way to planetary positions, as specified by either the    */
  979. /* -rb or -rd switches, respectively.                                       */
  980.  
  981. void DisplayRelation()
  982. {
  983.   char sz[cchSzDef];
  984.   int i;
  985. #ifdef BIORHYTHM
  986.   int j;
  987.   real k, l;
  988. #endif
  989.  
  990.   /* If we are calculating the difference between two dates, then display */
  991.   /* the value and return, as with the -rd switch.                        */
  992.  
  993.   if (us.nRel == rcDifference)
  994.   {
  995.     PrintSz("Differences between the dates in the two charts:\n");
  996.  
  997.     for (i = 1; i <= 7; i++)
  998.     {
  999.       AnsiColor(kRainbowA[i]);
  1000.       switch (i) {
  1001.       case 1: sprintf(sz, "Years  : %.0f", is.JD/365.25);      break;
  1002.       case 2: sprintf(sz, "Months : %.0f", is.JD/(365.25/12)); break;
  1003.       case 3: sprintf(sz, "Weeks  : %.0f", is.JD/7.0);         break;
  1004.       case 4: sprintf(sz, "Days   : %.0f", is.JD);             break;
  1005.       case 5: sprintf(sz, "Hours  : %.0f", is.JD*24.0);        break;
  1006.       case 6: sprintf(sz, "Minutes: %.0f", is.JD*24.0*60.0);   break;
  1007.       case 7: sprintf(sz, "Seconds: %.0f", is.JD*24.0*3600.0); break;
  1008.       }
  1009.       PrintSz(sz);
  1010.       PrintL();
  1011.     }
  1012.     AnsiColor(kDefault);
  1013.     return;
  1014.   }
  1015.  
  1016. #ifdef BIORHYTHM
  1017.   /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */
  1018.   /* someone born on the older date, at the time of the younger date. Loop */
  1019.   /* through the week preceeding and following the date in question.       */
  1020.  
  1021.   is.JD = RFloor(is.JD + rRound);
  1022.   for (is.JD -= 7.0, i = -7; i <= 7; i++, is.JD += 1.0)
  1023.   {
  1024.     if (i == 0)
  1025.       AnsiColor(kWhite);
  1026.     else if (i == 1)
  1027.       AnsiColor(kDefault);
  1028.     sprintf(sz, "T%c%d Day%c:",
  1029.       i < 0 ? '-' : '+', abs(i), abs(i) != 1 ? 's' : ' '); PrintSz(sz);
  1030.  
  1031.     for (j = 1; j <= 3; j++)
  1032.     {
  1033.       PrintCh(' ');
  1034.       switch (j) {
  1035.       case 1: k = brPhy; AnsiColor(kRed);   PrintSz("Physical");     break;
  1036.       case 2: k = brEmo; AnsiColor(kBlue);  PrintSz("Emotional");    break;
  1037.       case 3: k = brInt; AnsiColor(kGreen); PrintSz("Intellectual"); break;
  1038.       }
  1039.       AnsiColor(i ? kDefault : kWhite);
  1040.  
  1041.       /* The biorhythm calculation is below. */
  1042.  
  1043.       l = RBiorhythm(is.JD, k);
  1044.       sprintf(sz, " at %c%3.0f%%", l < 0.0 ? '-' : '+', RAbs(l)); PrintSz(sz);
  1045.  
  1046.       /* Print smiley face, medium face, or sad face based on current cycle. */
  1047.  
  1048.       AnsiColor(kPurple);
  1049.       sprintf(sz, " :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|'));
  1050.       PrintSz(sz);
  1051.       AnsiColor(i ? kDefault : kWhite);
  1052.       if (j < 3)
  1053.         PrintCh(',');
  1054.     }
  1055.     PrintL();
  1056.   }
  1057. #endif /* BIORHYTHM */
  1058. }
  1059.  
  1060. /* charts2.c */
  1061.